package cn.topevery.garden.wapi.controller.login;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.topevery.garden.entity.bo.CaptchaCacheBO;
import cn.topevery.garden.entity.bo.LoginFailCacheBO;
import cn.topevery.garden.wapi.config.HWProperties;
import cn.topevery.garden.wapi.exception.SystemRuntimeException;
import hw.topevery.basis.dal.logic.SysLoginErrorLogic;
import hw.topevery.basis.dal.util.UserUtil;

import hw.topevery.basis.entity.model.LoginParam;
import hw.topevery.basis.entity.po.SysLoginError;
import hw.topevery.basis.entity.po.SysUser;

import hw.topevery.basis.runtime.TokenData;
import hw.topevery.basis.runtime.UserRuntime;

import hw.topevery.framework.CacheExpireStrategyEnum;
import hw.topevery.framework.CacheRuntime;
import hw.topevery.framework.SystemConst;
import hw.topevery.framework.exception.TokenException;
import hw.topevery.framework.util.CaptchaUtil;
import hw.topevery.framework.web.JsonResult;
import hw.topevery.sso.framework.JwtProperties;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * @author eric.yang
 */
@Slf4j
@RestController
@RequestMapping("/")
public class AccountController extends BaseController {

    @Autowired
    private UserUtil sysUserLogic;
    @Autowired
    private HWProperties hwProperties;
    @Autowired
    private SysLoginErrorLogic sysLoginErrorLogic;

    private final String loginName = "admin";

    /**
     * post表单提交，登录
     *
     * @return
     * @loginParam username
     */
    @PostMapping("/login")
    public JsonResult<TokenData> login(@RequestBody @Valid LoginParam loginParam, HttpServletRequest request) {
        String loginName = loginParam.getLoginName();
//        if (!this.loginName.equals(loginName)) {
//            throw new SystemRuntimeException("权限不足，请使用超级管理员登陆");
//        }
        try {
            TokenData tokenData = this.doLogin(loginParam, request);
            CacheRuntime.removeCache(LoginFailCacheBO.PREFIX + loginParam.getLoginName());
            return JsonResult.ok(tokenData);
        } catch (Exception e) {
            //请求的IP
            String ip = request.getRemoteAddr();
            SysLoginError error = new SysLoginError();
            error.loginName = loginParam.getLoginName();
            error.loginIp = ip;
            error.loginTime = LocalDateTime.now();
            error.loginOutTime = 1;
            sysLoginErrorLogic.insert(SystemConst.UUID_EMPTY_STRING, error);
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 获取秘钥
     *
     * @return
     */
    @GetMapping("/getPublicKey")
    public JsonResult<String> getPublicKey() {
        //传输公钥给前端用户
        return JsonResult.ok(hwProperties.rsaPublicKey);
    }


    /**
     * 获取刷新后的token
     *
     * @param refreshToken 刷新的token令牌
     * @return 返回刷新后的token
     */
    @GetMapping("/refreshToken")
    public JsonResult<TokenData> refreshToken(@RequestParam String refreshToken) {
        JsonResult<TokenData> result = new JsonResult<>();
        if (StringUtils.isBlank(refreshToken) || StringUtils.isEmpty(refreshToken)) {
            throw new RuntimeException("token为空");
        }

        result.data = UserRuntime.refreshToken(sysUserLogic, refreshToken);
        result.success();
        return result;
    }

    @PostMapping("/logout")
    public String logout(HttpServletRequest request) throws Exception {
        String ip = request.getRemoteAddr();
        SysUser sysUser = UserRuntime.getSysUser();
        UserRuntime.logout();
        if (null != sysUser) {
            CacheRuntime.removeCache(LoginFailCacheBO.PREFIX + sysUser.loginName);
        }
        return "退出成功!";
    }

    @ApiOperation("验证码图片")
    @GetMapping("/captcha")
    public JsonResult<Map<String, String>> captcha(HttpServletRequest request) {
        return JsonResult.ok(getCaptcha(request));
    }
    @Value("${hw.pmi.omiUrl}")
    private String omiUrl;


    private TokenData doLogin(LoginParam loginParam, HttpServletRequest request) {
        String loginName = loginParam.getLoginName();
        System.out.println(omiUrl);
        String sessionId = request.getSession().getId();
        String ip = request.getRemoteAddr();
        LocalDateTime now = LocalDateTime.now();

        CaptchaCacheBO captchaCache = (CaptchaCacheBO) CacheRuntime.get(CaptchaCacheBO.PREFIX + sessionId);
        if (null != captchaCache) {
            if (StrUtil.isBlank(captchaCache.getCaptcha())) {
                throw new SystemRuntimeException("请输入验证码");
            }
            if (!StrUtil.equals(loginParam.getCaptcha(), captchaCache.getCaptcha())) {
                throw new SystemRuntimeException("验证码错误");
            }
            if (captchaCache.isExpired(now)) {
                throw new SystemRuntimeException("验证码已过期");
            }
        }
        LoginFailCacheBO failCache = (LoginFailCacheBO) CacheRuntime.get(LoginFailCacheBO.PREFIX + loginName);
        if (null != failCache) {
            if (failCache.isLock(now)) {
                throw new SystemRuntimeException(String.format("当前用户已锁定至%s", DateUtil.formatLocalDateTime(failCache.getLockExpireAt())));
            }
        }
        try {
            return UserRuntime.login(sysUserLogic, loginName, loginParam.getPassword(), true);
        } catch (TokenException e) {
            if (null == failCache) {
                failCache = new LoginFailCacheBO(loginName, now, ip);
                CacheRuntime.put(LoginFailCacheBO.PREFIX + loginName, failCache, 60*30, CacheExpireStrategyEnum.ByAccessDate, null);
            } else {
                failCache.addFailCount(now);
            }
            throw e;
        }
    }

    /**
     * 验证码
     *
     * @param request 请求
     * @return {@link JsonResult}<{@link Map}<{@link String}, {@link String}>>
     */
    private Map<String, String> getCaptcha(HttpServletRequest request) {
        String sessionId = request.getSession().getId();
        LocalDateTime now = LocalDateTime.now();

        String captcha = CaptchaUtil.generateCode();
        Map<String, String> captchaData = CaptchaUtil.generate(captcha);
        captchaData.put("code", captcha);
        if (StrUtil.isNotBlank(captcha)) {
            CaptchaCacheBO captchaCache = new CaptchaCacheBO(captcha, now);
            CacheRuntime.put(CaptchaCacheBO.PREFIX + sessionId, captchaCache, 60*10, CacheExpireStrategyEnum.ByWriteDate, null);
            return captchaData;
        }
        throw new SystemRuntimeException("验证码获取异常");
    }
}
